﻿using System;
using System.Net;
//using System.Data;
using System.Configuration;
using System.Linq;
//using System.Web;
//using System.Web.Security;
//using System.Web.UI;
//using System.Web.UI.HtmlControls;
//using System.Web.UI.WebControls;
//using System.Web.UI.WebControls.WebParts;
//using System.Xml.Linq;

using System.ComponentModel;
using System.Collections.ObjectModel;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.Serialization.Json;
using System.Text;


namespace VISUALFINDR
{
    // "{\"d\":{\"__type\":\"APISearchStatus:#Cortexica.API\",\"Count\":\"0\",\"Objects\":null,\"Status\":\"waiting\"}}";
    [DataContract]
    public class PollResponseDictionary
    {
        [DataMember]
        public PollResponseObject d { get; set; }
    }

    [DataContract]
    public class PollResponseObject
    {
        [DataMember(Name="__type")]
        public String __type { get; set; }
        [DataMember]
        public String Count { get; set; }
        [DataMember]
        public APIObject[] Objects { get; set; }
        [DataMember]
        public String Status { get; set; }
    }

    [DataContract]
    public class APIObject
    {
        [DataMember]
        public String Id {get; set;}
        [DataMember]
        public String Name { get; set; }
        [DataMember]
        public String Brief { get; set; }
        [DataMember]
        public APIObjectMetaData []Metadata { get; set; }        
    }

    [DataContract]
    public class APIObjectMetaData
    {
        [DataMember]
        public String Key { get; set; }
        [DataMember]
        public String Value { get; set; }
    }

    /*
     * 
     * {\"d\":{\"__type\":\"APISearchStatus:#Cortexica.API\",\"Count\":\"20\",\"Objects\":[{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Charles_Demuth_(24).jpg\",\"Id\":\"156943\",\"Metadata\":[],\"Name\":\"Charles_Demuth_(24).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Laura_Knight_(14).jpg\",\"Id\":\"169125\",\"Metadata\":[],\"Name\":\"Laura_Knight_(14).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Perugino_Pietro_Moses-s_Journey_into_Egypt_c1482.jpg\",\"Id\":\"175547\",\"Metadata\":[],\"Name\":\"Perugino_Pietro_Moses-s_Journey_into_Egypt_c1482.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Irolli_Vincenzo_View_Of_A_Terrace.jpg\",\"Id\":\"166373\",\"Metadata\":[],\"Name\":\"Irolli_Vincenzo_View_Of_A_Terrace.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Gustav_Klimt_(45).jpg\",\"Id\":\"164352\",\"Metadata\":[],\"Name\":\"Gustav_Klimt_(45).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Watwood_Patricia_Carnations_and_September.jpg\",\"Id\":\"183385\",\"Metadata\":[],\"Name\":\"Watwood_Patricia_Carnations_and_September.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Tamara_de_Lempicka_(12).jpg\",\"Id\":\"181003\",\"Metadata\":[],\"Name\":\"Tamara_de_Lempicka_(12).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Schendel_Petrus_van_The_Candlelit_Market.jpg\",\"Id\":\"179625\",\"Metadata\":[],\"Name\":\"Schendel_Petrus_van_The_Candlelit_Market.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Hills,_Laura_Coombs_(American,_1859-1952)3.jpg\",\"Id\":\"165577\",\"Metadata\":[],\"Name\":\"Hills,_Laura_Coombs_(American,_1859-1952)3.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Gustav_Klimt_(80).jpg\",\"Id\":\"164391\",\"Metadata\":[],\"Name\":\"Gustav_Klimt_(80).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Weyden_Deposition.jpg\",\"Id\":\"183523\",\"Metadata\":[],\"Name\":\"Weyden_Deposition.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Bierstadt_Albert_Sunset_on_the_Mountain.jpg\",\"Id\":\"154602\",\"Metadata\":[],\"Name\":\"Bierstadt_Albert_Sunset_on_the_Mountain.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Corot_Jean-Baptiste_Camille_Le_Monastere_Derriere_Les_Arbres.jpg\",\"Id\":\"157867\",\"Metadata\":[],\"Name\":\"Corot_Jean-Baptiste_Camille_Le_Monastere_Derriere_Les_Arbres.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Ribot_Augustin_Theodule_At_the_Sermon.jpg\",\"Id\":\"178246\",\"Metadata\":[],\"Name\":\"Ribot_Augustin_Theodule_At_the_Sermon.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"bosschaert2.jpg\",\"Id\":\"185164\",\"Metadata\":[],\"Name\":\"bosschaert2.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Herring_Snr_John_Frederick_Feeding_The_Arab.jpg\",\"Id\":\"165408\",\"Metadata\":[],\"Name\":\"Herring_Snr_John_Frederick_Feeding_The_Arab.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Raeburn_Sir_Henry_Colonel_Francis_James_Scott.jpg\",\"Id\":\"177088\",\"Metadata\":[],\"Name\":\"Raeburn_Sir_Henry_Colonel_Francis_James_Scott.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"dulac_blue5.jpg\",\"Id\":\"186225\",\"Metadata\":[],\"Name\":\"dulac_blue5.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Hardy_David_Garden_Of_The_Ancient_Oak.jpg\",\"Id\":\"164794\",\"Metadata\":[],\"Name\":\"Hardy_David_Garden_Of_The_Ancient_Oak.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Gustav_Klimt_(163).jpg\",\"Id\":\"164317\",\"Metadata\":[],\"Name\":\"Gustav_Klimt_(163).jpg\",\"Type\":\"\",\"Url\":\"\"}],\"Status\":\"matched\"}}
     **/

    public class PollUpdateState
    {
        public HttpWebRequest AsyncRequest { get; set; }
        public HttpWebResponse AsyncResponse { get; set; }
    }

    public class PollingController
    {
        public String LatestResponse;
        public String postData;
        public int counter;

        public void ForceReset()
        {
            counter = 0;
            Reset();
        }

        public void Reset()
        {
            LatestResponse = "";
            postData = "";
        }

        public String CleanJsonResponse(String jsonResponse)
        {
            String cleanedJsonResponse = jsonResponse;
            // I cant believe im forced to do this, but i give up:
            String evilString = "\"__type\":\"APISearchStatus:#Cortexica.API\",";
            if (jsonResponse.Contains(evilString))
                cleanedJsonResponse = jsonResponse.Replace(evilString, "");
            String evilString2 = "\"__type\":\"APIObjectInfo:#Cortexica.API\",";
            if (jsonResponse.Contains(evilString2))
                cleanedJsonResponse = cleanedJsonResponse.Replace(evilString2, "");
            String evilString3 = "\"__type\":\"APIObjectMetadata:#Cortexica.API\",";
            if (jsonResponse.Contains(evilString3))
                cleanedJsonResponse = cleanedJsonResponse.Replace(evilString3, "");
            return cleanedJsonResponse;
        }

        public void GetSearchIdStatusPhone(string searchId)
        {
            Reset();
            if (counter < SettingsController.MaxPoll())
            {
                counter++;
                String publicKey = SettingsController.PublicKey();

                UriBuilder fullUri = new UriBuilder(SettingsController.PollURL());

                // initialize a new WebRequest
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(fullUri.Uri);
                webRequest.ContentType = "application/json";
                webRequest.Method = "POST";

                // TODO: Add other security info!
                postData = "{\"publicKey\":\"" + publicKey + "\",\"id\":\"" + searchId + "\"}";

                // set up the state object for the async request
                PollUpdateState pollUpdateState = new PollUpdateState();
                pollUpdateState.AsyncRequest = webRequest;

                webRequest.BeginGetRequestStream(new AsyncCallback(HandleSearchIdRequest), pollUpdateState);
            }
            else
            {
                LatestResponse = "Failed";
            }
        }

        private void HandleSearchIdRequest(IAsyncResult asyncResult)
        {
            // get the state information
            PollUpdateState pollUpdateState = (PollUpdateState)asyncResult.AsyncState;
            HttpWebRequest webRequest = (HttpWebRequest)pollUpdateState.AsyncRequest;

            // Add post data
            //using (StreamWriter writer = new StreamWriter(webRequest.EndGetRequestStream(asyncResult),System.Text.Encoding.UTF8))
            using (StreamWriter writer = new StreamWriter(webRequest.EndGetRequestStream(asyncResult)))
            {
                //writer.Write(postData); // needs ascii

                // add image first
                Stream rs = writer.BaseStream;
                byte[] postDataBytes = System.Text.Encoding.UTF8.GetBytes(postData);
                rs.Write(postDataBytes, 0, postDataBytes.Length);
                rs.Close();
            }

            // start the asynchronous request
            webRequest.BeginGetResponse(new AsyncCallback(HandleSearchIdResponse),
                pollUpdateState);
        }

  
        /// <summary>
        /// Handle the information returned from the async request
        /// </summary>
        /// <param name="asyncResult"></param>
        private void HandleSearchIdResponse(IAsyncResult asyncResult)
        {
            // get the state information
            PollUpdateState pollUpdateState = (PollUpdateState)asyncResult.AsyncState;
            HttpWebRequest webRequest = (HttpWebRequest)pollUpdateState.AsyncRequest;

            try
            {
                // end the async request
                pollUpdateState.AsyncResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult);
                Stream streamResult = pollUpdateState.AsyncResponse.GetResponseStream();
                StreamReader r = new StreamReader(streamResult);
                String responseString = r.ReadToEnd();
                Debug.WriteLine(responseString);
                LatestResponse = responseString;
            }
            catch (Exception e)
            {
                if (counter>SettingsController.MaxPoll())
                    LatestResponse = "Failed";
            }
        }

        public String Objects()
        {
            return Objects(LatestResponse);
        }

        public String Objects(String str)
        {
            String jsonResponse = str;

            if (jsonResponse != null && jsonResponse.Length > 0)
            {
                if (jsonResponse == "Failed")
                    return jsonResponse;

                String cleanedJsonResponse = jsonResponse;

                // I cant believe im forced to do this, but i give up:
                String evilString = "\"__type\":\"APISearchStatus:#Cortexica.API\",";
                if (jsonResponse.Contains(evilString))
                    cleanedJsonResponse = jsonResponse.Replace(evilString, "");
                String evilString2 = "\"__type\":\"APIObjectInfo:#Cortexica.API\",";
                if (jsonResponse.Contains(evilString2))
                    cleanedJsonResponse = cleanedJsonResponse.Replace(evilString2, "");
                String evilString3 = "\"__type\":\"APIObjectMetadata:#Cortexica.API\",";
                if (jsonResponse.Contains(evilString3))
                    cleanedJsonResponse = cleanedJsonResponse.Replace(evilString3, "");

                //str	"{\"d\":{\"__type\":\"APISearchStatus:#Cortexica.API\",\"Count\":\"3\",\"Objects\":[{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"1.4500\",\"Id\":\"0\",\"Metadata\":[],\"Name\":\"3105\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"1.2400\",\"Id\":\"0\",\"Metadata\":[],\"Name\":\"794\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"0.9000\",\"Id\":\"0\",\"Metadata\":[],\"Name\":\"31\",\"Type\":\"\",\"Url\":\"\"}],\"Status\":\"matched\"}}"	string

                PollResponseDictionary d = new PollResponseDictionary();
                MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(cleanedJsonResponse));
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(d.GetType());
                d = serializer.ReadObject(ms) as PollResponseDictionary;
                ms.Close();
                return d.d.Objects.ToString();
            }
            return "Unknown";
        }

        public String Status()
        {
            return Status(LatestResponse);
        }

        public String Status(String str)
        {
            String jsonResponse = str;

            if (jsonResponse != null && jsonResponse.Length>0)
            {
                if (jsonResponse == "Failed")
                    return jsonResponse;

                String cleanedJsonResponse = jsonResponse;

                // I cant believe im forced to do this, but i give up:
                String evilString = "\"__type\":\"APISearchStatus:#Cortexica.API\",";
                if (jsonResponse.Contains(evilString))
                    cleanedJsonResponse = jsonResponse.Replace(evilString, "");
                String evilString2 = "\"__type\":\"APIObjectInfo:#Cortexica.API\",";
                if (jsonResponse.Contains(evilString2))
                    cleanedJsonResponse = cleanedJsonResponse.Replace(evilString2, "");
                String evilString3 = "\"__type\":\"APIObjectMetadata:#Cortexica.API\",";
                if (jsonResponse.Contains(evilString3))
                    cleanedJsonResponse = cleanedJsonResponse.Replace(evilString3, "");

                PollResponseDictionary d = new PollResponseDictionary();
                MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(cleanedJsonResponse));
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(d.GetType());
                d = serializer.ReadObject(ms) as PollResponseDictionary;
                ms.Close();
                return d.d.Status;
            }
                return "Unknown";
        }

        public bool shouldPoll()
        {
            String lResp = LatestResponse;
            String status = Status(lResp);
            if (lResp == null || lResp.Length == 0 || status == "waiting" || status=="in progress" || status=="failed")
                return true;
            else
                return false;
        }
    }
}
